using System;
using System.Collections;
using UnityEngine;

namespace EventBehaviorTree
{
    [Serializable]
    public class CountdownSequencer : Container<TriggerMode>
    {
        private int _remainFrame;
        private int _duration;
        private int RemainFrame { get => _remainFrame; set => _remainFrame = Mathf.Max(0, value); }
        private int Duration { get => _duration; set => _duration = Mathf.Max(0, value); }
        public CountdownSequencer(int duration, string workMode)
        {
            Duration = duration;
            _workMode = (TriggerMode)Enum.Parse(typeof(TriggerMode), workMode);
            Condition = () => RemainFrame > 0;//while the timer is working
        }

        protected override IEnumerator Worker()
        {
            switch (_workMode)
            {
                case TriggerMode.Async:
                    _subNodes[0].NodeEvent(NodeMessage.Start);
                    break;
                case TriggerMode.AsyncDelay:
                    SeniorNodeEvent(NodeMessage.Success);//the coroutine has been started successfully
                    break;
                case TriggerMode.Busy:
                    _subNodes[0].NodeEvent(NodeMessage.Start);
                    break;
                case TriggerMode.Delay:
                    break;
                default:
                    break;
            }
            RemainFrame = Duration;
            while (Condition())
            {
                yield return null;
                RemainFrame--;
                //Debug.Log(RemainFrame);
            }
            switch (_workMode)
            {
                case TriggerMode.Async:
                    StopAllSubNodes();//time up, stop the sub coroutine
                    break;
                case TriggerMode.AsyncDelay:
                    _subNodes[0].NodeEvent(NodeMessage.Start);
                    break;
                case TriggerMode.Busy:
                    StopAllSubNodes();//time up, stop the sub coroutine
                    SeniorNodeEvent(NodeMessage.Success);
                    break;
                case TriggerMode.Delay:
                    if (_subNodes.Count == 0) SeniorNodeEvent(NodeMessage.Success);//just a timer
                    else _subNodes[0].NodeEvent(NodeMessage.Start);
                    break;
                default:
                    break;
            }
            ResetWorker();
        }

        public override void NodeEvent(NodeMessage nodeMessage)
        {
            switch (nodeMessage)
            {
                case NodeMessage.Start:
                    _stepCount = 0;
                    ResetWorker();
                    _coroutineStarter.StartCoroutine(_worker);
                    return;
                case NodeMessage.Success:
                    if (_stepCount < _subNodes.Count - 1)
                    {
                        _subNodes[++_stepCount].NodeEvent(NodeMessage.Start);
                        return;
                    }
                    switch (_workMode)// the last sub node will do this: all successed
                    {
                        case TriggerMode.Async:
                            SeniorNodeEvent(NodeMessage.Success);
                            return;
                        case TriggerMode.AsyncDelay://never stop sub nodes, so the sub nodes is better to be the instant task
                            SeniorNodeEvent(NodeMessage.Success);
                            return;
                        case TriggerMode.Busy:
                            return;
                        case TriggerMode.Delay://never stop sub nodes, so the sub nodes is better to be the instant task
                            SeniorNodeEvent(NodeMessage.Success);
                            return;
                        default:
                            return;
                    }
                case NodeMessage.Failure:
                    ResetWorker();
                    StopAllSubNodes();
                    SeniorNodeEvent(NodeMessage.Failure);
                    return;
                case NodeMessage.COMMAND_Stop:
                    ResetWorker();
                    StopAllSubNodes();
                    return;
                case NodeMessage.REQUEST_Abort:
                    ResetWorker();
                    StopAllSubNodes();
                    SeniorNodeEvent(NodeMessage.Success);//[HelpDoc]
                    return;
                default:
                    return;
            }
        }
    }
}